<template>
  <el-dialog
    title="新增预约"
    :visible="addDialog"
    width="70%"
    @close="$emit('close')"
    append-to-body
  >
    <el-form
      ref="form"
      :model="form"
      :rules="rules"
      label-position="right"
      label-width="80px"
    >
      <el-form-item label="实验室" prop="labId">
        <el-select
          v-model="form.labId"
          placeholder="请选择实验室"
          style="width: 80%;"
          @change="changeLabId"
        >
          <el-option
            v-for="item in appointmentLabs"
            :key="item.labId"
            :label="item.labName"
            :value="item.labId"
          />
          <!-- <el-option
            v-for="item in allLabs"
            :key="item.id"
            :label="item.name"
            :value="item.id"
          /> -->
        </el-select>
      </el-form-item>
      <el-form-item label="预约时间" prop="times">
        <!-- 选择日期的日历表 -->
        <full-calendar
          v-show="showMonth"
          id="schedulerCalendar"
          ref="calendar"
          style="margin-bottom: 30px;"
          :events="events"
          :config="config"
        />

        <!-- 预约时间选择表 -->
        <div v-show="!showMonth" class="timeFullCalendar">
          <!-- <div class="back">重新选择日期</div> -->
          <el-button
            icon="el-icon-refresh-left"
            type="primary"
            class="back"
            @click="backDate"
            >重新选择日期</el-button
          >
          <full-calendar
            id="agendaDayCalendar"
            ref="agendaDayCalendar"
            :events="agendaDayEvents"
            :config="agendaDayConfig"
          />
        </div>
      </el-form-item>

      <el-form-item label="备注" prop="note">
        <el-input
          v-model="form.note"
          class="textarea"
          style="width: 55%;"
          type="textarea"
          placeholder="请输入内容"
        />
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <el-button @click="onCancel">取 消</el-button>
      <el-button type="primary" @click="onAdd">确 定</el-button>
    </span>
  </el-dialog>
</template>

<script>
import {
  getAppointmentTimeAPI,
  addAppointmentAPI,
  getAppointmentLabAPI
} from "@/api/web/hjUser.js";
import { FullCalendar } from "vue-full-calendar";
import "fullcalendar/dist/fullcalendar.css";
// import FullCalendar from '@fullcalendar/vue'
import dataFormat from "js-dateformat";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import momentPlugin from "@fullcalendar/moment";
import { timestampFormat } from "@/utils/index";
import moment from "moment";
import { mapState } from "vuex";
export default {
  components: { FullCalendar },
  props: {
    addDialog: {
      type: Boolean,
      default: false
    }
  },
  data() {
    const that = this;
    const dateFormat = dataFormat.dateFormat;
    return {
      form: {
        labId: 1,
        date: "", // 日期
        note: "",
        times: []
      },
      rules: {
        labId: [
          { required: true, message: "请选择要预约的实验室", trigger: "blur" }
        ],
        times: [
          { required: true, message: "请选择要预约的时间", trigger: "blur" }
        ]
      },
      appointmentLabs: [], // 可预约的实验室
      chosedTimes: [],
      showMonth: true,
      config: {
        locale: "zh-cn",
        defaultView: "month",
        selectAllow: function(clickInfo) {
          // 不可被拖动
          return false;
        },
        // weekends: false,
        // 点击后检测是否有预约仪器的权限；然后跳转到议程选择页面，设置好能够选择的时间和不能选择的时间
        dayClick(date, allDay, jsEvent, view) {
          if (jsEvent.type === "month") {
            const selectDate = dateFormat(date._d, "yyyy-mm-dd");
            if (that.bookTimeDate.includes(selectDate)) {
              that.form.date = selectDate;
              that.showMonth = false;
              setTimeout(function() {
                that.$refs.agendaDayCalendar.fireMethod(
                  "changeView",
                  "agendaDay",
                  moment(new Date().getFullYear() + 1 + "-01-01")
                );
                that.$refs.agendaDayCalendar.fireMethod(
                  "changeView",
                  "agendaDay",
                  date
                );
              }, 150);
            } else {
              that.$message({
                message: dateFormat(date._d, "yyyy年mm月dd日") + "不可预约时间",
                type: "error"
              });
            }
          }
        },
        // 点击后检测是否有预约仪器的权限；然后跳转到议程选择页面，设置好能够选择的时间和不能选择的时间
        eventClick(event, jsEvent, view) {
          const selectDate = dateFormat(event.start._d, "yyyy-mm-dd");
          if (that.bookTimeDate.includes(selectDate)) {
            that.form.date = selectDate;
            that.showMonth = false;
            setTimeout(function() {
              that.$refs.agendaDayCalendar.fireMethod(
                "changeView",
                "agendaDay",
                moment(new Date().getFullYear() + 1 + "-01-01")
              );
              that.$refs.agendaDayCalendar.fireMethod(
                "changeView",
                "agendaDay",
                event.start
              );
            }, 50);
          } else {
            that.$message({
              message: dateFormat(date._d, "yyyy年mm月dd日") + "不可预约时间",
              type: "error"
            });
          }
        },
        allDaySlot: false,
        isDragging: false,
        header: {
          left: "prev,next",
          center: "title",
          right: ""
        }
      },
      nowTime: 0,
      appointmented: [], // 已经预约过得
      events: [], // 日历工具
      bookTimeDate: [], // 可预约时间的日期
      unappointmented: [], // 不可预约时间具体段
      appointment: {}, // 可预约的时间
      calendarPlugins: [
        dayGridPlugin,
        timeGridPlugin,
        momentPlugin,
        interactionPlugin
      ],
      agendaDayEvents: [], // 一天内的时间选择，议程
      agendaDayConfig: {
        locale: "zh-cn",
        defaultView: "agendaDay",
        allDaySlot: false,
        slotDuration: "00:10:00",
        slotLabelFormat: "HH:mm",
        minTime: "00:00:00",
        maxTime: "24:00:00",
        slotEventOverlap: false, // 事件是否允许重叠
        scrollTime: "08:00:00",
        header: {
          left: "",
          center: "title",
          right: ""
        },
        selectAllow: function(clickInfo) {
          const start = clickInfo.start.unix() - 8 * 3600;
          const end = clickInfo.end.unix() - 8 * 3600;

          // 不能预约以前的时间
          if (start <= that.nowTime || end <= that.nowTime) {
            return false;
          }
          var canSelect = false;
          if (that.unappointmented.length > 0) {
            that.unappointmented.forEach(item => {
              if (
                (start > item.start && start < item.end) ||
                (end > item.start && end <= item.end)
              ) {
                canSelect = false; // 选择时间在不可预约时间内
              } else {
                canSelect = true;
              }
            });
          }
          that.appointmented.forEach(item => {
            if (
              (start >= item.start_at && start < item.end_at) ||
              (end > item.start_at && end <= item.end_at) ||
              (end >= item.end_at && start <= item.start_at)
            ) {
              canSelect = false; // 在已选择的时间内
            } else {
              canSelect = true;
            }
          });
          if (that.chosedTimes.length > 0) {
            that.chosedTimes.forEach(item => {
              if (
                (start > item.start && start < item.end) ||
                (end > item.start && end <= item.end)
              ) {
                canSelect = false;
              } else {
                canSelect = true;
              }
            });
          }
          return canSelect;
        },
        select: function(startDate, endDate, allDay, jsEvent, view) {
          // 选中
          const start = startDate._i; // [年， 月，日， 时，分，秒]
          const end = endDate._i;
          if (jsEvent.type === "agendaDay") {
            const startAt =
              "" + that.getFulldate(start[3]) + that.getFulldate(start[4]);
            const endAt =
              "" + that.getFulldate(end[3]) + that.getFulldate(end[4]);
            const startTime = `${start[0]}-${that.getFulldate(
              start[1] + 1
            )}-${that.getFulldate(start[2])} ${that.getFulldate(
              start[3]
            )}:${that.getFulldate(start[4])}`;
            const endTime = `${end[0]}-${that.getFulldate(
              end[1] + 1
            )}-${that.getFulldate(end[2])} ${that.getFulldate(
              end[3]
            )}:${that.getFulldate(end[4])}`;

            that.form.times.push({
              start: new Date(startTime).getTime(),
              end: new Date(endTime).getTime()
            });
            that.chosedTimes.push({
              start: startDate.unix() - 8 * 3600,
              end: endDate.unix() - 8 * 3600
            });
            that.agendaDayEvents.push({
              flag: "book_time",
              resourceId: new Date().getTime(),
              title: "已选择时间段 (点击取消选择)",
              start: startDate,
              end: endDate,
              color: "blue",
              textColor: "#ffffff",
              editable: false,
              selectable: false
            });
          }
        },
        eventClick(event, jsEvent, view) {
          // 有颜色部分点击
          if (event.flag && event.flag == "not_open_time") {
            // 不可预约的时间段，不做任何处理
            return false;
          }
          const start = event.start.unix() - 8 * 3600;
          const end = event.end.unix() - 8 * 3600;

          let canDelete = true;
          // 已经被预约的时间
          that.appointmented.forEach(item => {
            if (
              (start > item.start_at && start < item.end_at) ||
              (end > item.start_at && end <= item.end_at)
            ) {
              canDelete = false;
            }
          });
          if (!canDelete) return;

          // 再次点击取消预约时间选择
          that.agendaDayEvents.forEach((item, index) => {
            if (item.resourceId === event.resourceId) {
              that.agendaDayEvents.splice(index, 1);
              const formTimeINdex = that.form.times.findIndex(
                item => item.start == start && item.end == end
              );
              that.form.times.splice(formTimeINdex, 1);
              that.chosedTimes.forEach((time, timeIndex) => {
                if (time.start == start && time.end == end) {
                  that.chosedTimes.splice(timeIndex, 1);
                }
              });
            }
          });
        }
      }
    };
  },
  async created() {
    const res = await getAppointmentLabAPI();
    this.appointmentLabs = res;
    this.nowTime = moment().unix();
    this.getBookingTime(1);
  },
  computed: {
    ...mapState("hjuser", ["allLabs"])
  },
  methods: {
    changeLabId(val) {
      this.getBookingTime(val);
    },
    onCancel() {
      this.form = {};
      this.$emit("close");
    },
    onAdd() {
      this.$refs.form.validate(async valid => {
        if (!valid) return;
        // 调用添加的接口
        try {
          await addAppointmentAPI(this.form);
          this.onCancel();
          this.$message.success("新增成功");
          this.$emit("success");
        } catch {
          this.$message.error("新增失败");
        }
      });
    },
    async getBookingTime(id) {
      const that = this;
      that.events = [];
      that.agendaDayEvents = [];
      that.appointmented = [];
      that.bookTimeDate = [];
      that.chosedTimes = [];
      that.unappointmented = [];
      that.appointment = {};
      const res1 = await getAppointmentTimeAPI(id);
      if (!res1.bookTime) return;
      // console.log(111, res1);
      const bookTime = JSON.parse(res1.bookTime.bookTime);
      // console.log(555, bookTime);
      // this.bookTimeDate = res1.datesDetail
      this.bookTimeDate = res1.datesDetail.filter(item => {
        return (
          new Date(item).getTime() >=
          new Date(new Date().toLocaleDateString()).getTime()
        );
      });

      this.bookTimeDate.forEach(item => {
        const startTime = new Date(item + " 00:00:00").getTime();
        const endTime = new Date(item + " 23:59:59").getTime();
        const startArr = bookTime
          .map(start => new Date(item + " " + start.start).getTime())
          .sort((a, b) => a - b);
        const endArr = bookTime
          .map(end => new Date(item + " " + end.end).getTime())
          .sort((a, b) => a - b);
        let endpush;
        endArr.forEach((v, i) => {
          if (i === endArr.length - 1) {
            endpush = endTime;
          } else {
            endpush = startArr[i + 1];
          }

          that.agendaDayEvents.push({
            flag: "not_open_time",
            title: "未开放预约",
            start: timestampFormat("Y-m-dTH:i:s", v / 1000),
            end: timestampFormat("Y-m-dTH:i:s", endpush / 1000),
            color: "#dee2e6",
            textColor: "#999",
            selectable: false,
            editable: false
          });
          that.unappointmented.push({
            start: v,
            end: endpush
          });
        });
        if (startArr[0] > startTime) {
          that.agendaDayEvents.push({
            flag: "not_open_time",
            title: "未开放预约",
            start: timestampFormat("Y-m-dTH:i:s", startTime / 1000),
            end: timestampFormat("Y-m-dTH:i:s", startArr[0] / 1000),
            color: "#dee2e6",
            textColor: "#999",
            selectable: false,
            editable: false
          });
          that.unappointmented.push({
            start: startTime,
            end: startArr[0]
          });
        }

        this.$set(that.appointment, item, []);
        bookTime.forEach(time => {
          that.appointment[item].push({
            start: new Date(item + " " + time.start).getTime(),
            end: new Date(item + " " + time.end).getTime()
          });
        });
      });
      const date = Object.keys(that.appointment)[0];
      var totalTime = 0;
      that.appointment[date].forEach(item => {
        totalTime += item.end - item.start;
      });

      let bookedDateTime = {}; // 每天已经预约过得时间,按日期划分
      res1.bookedTime.forEach(item => {
        const key = moment(Number(JSON.parse(item.times)[0].start)).format(
          "YYYY-MM-DD"
        );
        if (!bookedDateTime.hasOwnProperty(key)) {
          bookedDateTime[key] = [...JSON.parse(item.times)];
        } else {
          bookedDateTime[key].push(...JSON.parse(item.times));
        }
      });

      let bookedDayTotalTime = {}; // 每天预约过时间的总时间戳，,按日期划分
      let nowbookedTotalTime = 0;
      let now = new Date().getTime();
      for (let key in bookedDateTime) {
        if (key == moment(moment()).format("YYYY-MM-DD")) {
          bookedDateTime[key].forEach(item => {
            if (item.start >= now && item.end >= now) {
              nowbookedTotalTime += item.end - item.start;
            } else if (item.start < now && item.end >= now) {
              nowbookedTotalTime += item.end - now;
            }
          });
        }
        bookedDayTotalTime[key] = 0;
        bookedDateTime[key].forEach(item => {
          bookedDayTotalTime[key] += item.end - item.start;
        });
      }
      let seconds = 0;
      let hours = 0;
      let minute = 0;
      this.bookTimeDate.forEach(item => {
        if (moment(new Date()).format("YYYY-MM-DD") == item) {
          let totalTimeToday = 0;
          that.appointment[item].forEach(v => {
            if (v.start >= now && v.end >= now) {
              totalTimeToday += v.end - v.start;
            } else if (v.start < now && v.end >= now) {
              totalTimeToday += v.end - now;
            }
          });
          if (totalTimeToday > 0) {
            seconds = (totalTimeToday - (nowbookedTotalTime || 0)) / 1000;
            hours = Math.floor(seconds / 3600);
            minute = Math.floor(seconds / 60) % 60;
          }
        } else if (bookedDayTotalTime[item]) {
          if (bookedDayTotalTime[item] >= totalTime) {
            that.events.push({
              title: "已约满",
              start: item,
              color: "gray",
              textColor: "#ffffff",
              editable: false,
              selectable: false
            });
          } else {
            seconds = (totalTime - bookedDayTotalTime[item]) / 1000;
            hours = Math.floor(seconds / 3600);
            minute = Math.floor(seconds / 60) % 60;
          }
        } else {
          hours = Math.floor(totalTime / 1000 / 3600);
          minute = Math.floor(totalTime / 1000 / 60) % 60;
        }
        if (minute / 10 < 1) {
              minute = 0;
            } else {
              minute = minute.toString().slice(0, 1) * 10;
            }
        that.events.push({
          title: "可预约",
          start: item,
          color: "#64a1ff",
          textColor: "#ffffff",
          editable: false,
          selectable: false
        });
        that.events.push({
          title: "剩余" + hours + "小时" + minute + "分钟",
          start: item,
          color: "#64a1ff",
          textColor: "#ffffff",
          editable: false,
          selectable: false
        });
      });

      // 已被预约时间段，不分日期
      res1.bookedTime.forEach(item => {
        this.appointmented.push(...JSON.parse(item.times));
      });
      this.appointmented.forEach(item => {
        that.agendaDayEvents.push({
          flag: "not_open_time",
          title: "已被预约",
          start: timestampFormat(
            "Y-m-dTH:i:s",
            (item.start || item.start_at) / 1000
          ),
          end: timestampFormat("Y-m-dTH:i:s", (item.end || item.end_at) / 1000),
          color: "red",
          textColor: "#999",
          selectable: false,
          editable: false
        });
      });
    },
    gettime(data) {
      return data.map(v => ({
        start: moment(v.start).format("YYYY-MM-DD HH:mm:ss"),
        end: moment(v.end).format("YYYY-MM-DD HH:mm:ss")
      }));
    },
    getFulldate(time) {
      if (time < 10) {
        time = "0" + time;
      }
      return time;
    },
    backDate() {
      this.showMonth = true;
      this.form.times = []
    }
  }
};
</script>

<style scoped lang="scss">
.el-dialog__wrapper ::v-deep .el-dialog {
  border-radius: 10px;

  .fc-state-default {
    background-color: #448ef7;
    background-image: unset;
    box-shadow: unset;
  }
  .fc-state-default:hover {
    filter: brightness(115%);
  }
  .fc-icon-right-single-arrow:after,
  .fc-icon-left-single-arrow:after {
    font-size: 28px;
    color: #fff;
    top: -35%;
  }
  .fc-unthemed td.fc-today {
    background-color: #eaf4fe;
  }
  .fc {
    margin-top: 30px;
    margin-bottom: 18px;

    th {
      background-color: #64a1ff;
      color: #fff;
    }
  }
  .timeFullCalendar {
    position: relative;
    width: 90%;
    .back {
      position: relative;
      left: 7px;
      top: 60px;
    }

    .fc-scroller,
    .fc-time-grid-container {
      height: 350px !important;
    }
  }
}
.el-textarea ::v-deep {
  .el-textarea__inner {
    height: 120px;
  }
}
</style>
